<template>
  <div class="pen">
    <div class="markdown">
      <div
        ref="inputElement"
        class="markdown-input"
        :contenteditable="!disabled"
        placeholder="请输入你的见解"
      ></div>
      <transition name="list-fade">
        <div class="markdown-preview markdown-html comment" v-if="preview" v-html="previewContent" />
      </transition>
    </div>
    <div class="pencilbox">
      <div class="stationery">
        <button class="emoji" title="emoji" type="button" :disabled="disabled || preview">
          <i class="iconfont icon-emoji" />
          <div class="emoji-box">
            <ul class="emoji-list">
              <li
                v-for="(emoji, index) in EMOJIS"
                v-once
                :key="index"
                class="item"
                @click="insertEmoji(emoji)"
              >{{ emoji }}</li>
            </ul>
          </div>
        </button>
        <!-- <button class="image" title="image" :disabled="disabled || preview" @click.prevent="insertImage">
          <i class="iconfont icon-image" />
        </button>
        <button class="link" title="link" :disabled="disabled || preview" @click.prevent="insertLink">
          <i class="iconfont icon-link" />
        </button>
        <button class="code" title="code" :disabled="disabled || preview" @click.prevent="insertCode">
          <i class="iconfont icon-code" />
        </button>
        <button class="preview" title="preview" :class="{ actived: preview }" :disabled="disabled" @click.prevent="handleTogglePreview">
          <i class="iconfont" :class="preview ? 'icon-eye-close' : 'icon-eye'" />
        </button>-->
      </div>
      <button type="submit" class="submit" :disabled="disabled" @click="handleSubmit">
        <span>{{ posting ? "提交中.." : "提交" }}</span>
      </button>
    </div>
  </div>
</template>

<script>
import { defineComponent, ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
import { insertContent } from "@/utils/editable";
import { markdownToHTML } from "@/transforms/markdown";
import { EMOJIS } from "./helper";

// export enum Events {
//   Update = 'update:modelValue',
//   InputReady = 'input-ready'
// }

export default defineComponent({
  name: 'CommentPen',
  props: {
    modelValue: {
      type: String,
      required: true
    },
    disabled: {
      type: Boolean,
      required: true
    },
    posting: {
      type: Boolean,
      required: true
    },
    preview: {
      type: Boolean,
      required: true
    }
  },
  emits: [
    'update:modelValue',
    'input-ready',
    'toggle-preview',
    'submit'
  ],
  setup(props, context) {
    const content = ref(props.modelValue)
    const inputElement = ref(null)
    let inputElementObserver = null
    const previewContent = computed(() => {
      return props.preview
        ? markdownToHTML(content.value)
        : null
    })

    const handleTogglePreview = () => {
      context.emit('toggle-preview')
    }

    const handleValueChange = (value) => {
      if (value !== content.value) {
        content.value = value
        if (inputElement.value) {
          inputElement.value.innerText = value
        }
      }
    }

    const handleInputChange = () => {
      const text = inputElement.value?.innerText
      if (text !== content.value) {
        content.value = text
        context.emit('update:modelValue', text)
      }
    }

    const handleSubmit = (event) => {
      event.preventDefault()
      context.emit('submit', content.value)
    }

    const insertContentToInput = (before, after = '') => {
      insertContent({
        element: inputElement.value,
        content: [before, after]
      })
      handleInputChange()
    }
    const insertEmoji = (emoji) => {
      insertContentToInput(` ${emoji} `)
    }
    const insertImage = () => {
      insertContentToInput(` ![`, `](https://) `)
    }
    const insertLink = () => {
      insertContentToInput(` [`, `](https://) `)
    }
    const insertCode = () => {
      insertContentToInput('\n```javascript\n', '\n```\n')
    }

    watch(() => props.modelValue, handleValueChange)

    onMounted(() => {
      context.emit('input-ready', inputElement.value)
      inputElementObserver = new MutationObserver(mutations => {
        handleInputChange()
      })
      inputElementObserver.observe(inputElement.value, {
        attributes: true,
        characterData: true,
        childList: true,
        subtree: true
      })
    })
    onBeforeUnmount(() => {
      inputElementObserver?.disconnect()
    })

    return {
      EMOJIS,
      inputElement,
      previewContent,
      insertEmoji,
      insertImage,
      insertLink,
      insertCode,
      handleInputChange,
      handleTogglePreview,
      handleSubmit
    }
  }
})
</script>

<style lang="scss" scoped>
.pen {
  position: relative;
  @include radius-box($xs-radius);

  .markdown {
    position: relative;
    overflow: hidden;

    .markdown-input {
      min-height: 6em;
      max-height: 36em;
      overflow: auto;
      outline: none;
      padding: 0.5em;
      cursor: auto;
      font-size: $font-size-h6;
      line-height: 1.8em;
      background-color: $module-bg-darker-1;
      @include background-transition();

      &:empty:before {
        content: attr(placeholder);
        color: $text-disabled;
      }

      &:focus {
        content: none;
      }

      &:hover {
        background-color: $module-bg-hover;
      }
    }

    .markdown-preview {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      overflow: auto;
      margin: 0;
      padding: 0.5em;
      background-color: $body-bg;
    }
  }

  .pencilbox {
    $size: $font-size-base * 2;
    height: $size;
    line-height: $size;
    display: flex;
    justify-content: space-between;
    background-color: $module-bg-darker-3;

    .stationery {
      .emoji,
      .image,
      .link,
      .code,
      .preview {
        width: $size;
        height: $size;
        text-align: center;
        display: block;
        float: left;
        @include background-transition();

        &[disabled] {
          opacity: 0.7;
        }

        &:not([disabled]) {
          &.actived,
          &:hover {
            background-color: $module-bg-darker-4;
          }
        }
      }

      .emoji {
        &:not([disabled]):hover {
          .emoji-box {
            display: block;
          }
        }

        .emoji-box {
          display: none;
          position: absolute;
          bottom: $size;
          left: 0;
          top: 0;
          width: 100%;
          overflow-y: auto;
          background-color: $module-bg;

          .emoji-list {
            list-style: none;
            padding: 0;
            margin: 0;
            font-size: $font-size-h3;
            display: flex;
            flex-wrap: wrap;

            .item {
              padding: 0 0.4em;
              cursor: pointer;
              @include background-transition();

              &:hover {
                background-color: $module-bg-hover;
              }
            }
          }
        }
      }
    }

    .submit {
      width: 8rem;
      height: $size;
      background-color: $module-bg-darker-4;
      @include background-transition();

      &:hover {
        background-color: $module-bg-darker-5;
      }
    }
  }
}
</style>
